home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-03-07 | 29.6 KB | 1,021 lines |
- Newsgroups: comp.sources.misc
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Subject: v06i062: A library for command argument parsing for C
- Message-Id: <705@gould.doc.ic.ac.uk>
- Distribution: world
- Organization: Dept. of Computing, Imperial College, London, UK.
- Reply-To: Nigel Perry <np@doc.ic.ac.uk>
-
- Posting-number: Volume 6, Issue 62
- Submitted-by: Nigel Perry <np@doc.ic.ac.uk>
- Archive-name: copt
-
- [ Getopt is here to stay, but for those who don't like it...
- Manpages would help. --r$ ]
-
- [This is silly. One person thinks to overcome the trend toward standardized
- option processing? Easier to convert the Ayatollah to Catholicism. And has
- the author given any thought to how one would use a wildcard in his string
- options? (hint: "dd if=ar*xy of=/dev/rmt8" fails.) ++bsa]
-
- This is a library which contains routines to perform nice
- parsing of command lines for C programs, no more "-letter" options
- for everything now you can have +option, -option, option=value etc.
-
- Nigel
-
- --- cut here ---
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # README
- # abbrev.c
- # cset.c
- # cset.d
- # cset.h
- # d_optable.c
- # demo.c
- # makefile
- # not_kwd.c
- # numarg.c
- # This archive created: Fri Mar 3 12:57:09 1989
- export PATH; PATH=/bin:$PATH
- if test -f 'README'
- then
- echo shar: will not over-write existing file "'README'"
- else
- cat << \SHAR_EOF > 'README'
- Description
- ===========
-
- A radical departure fro Unix - proper command line parsing!
-
- This is a library to replace getopt() or simple "-" option processing by a program.
- It provies automatic scanning switch options, + to turn on, - to turn off; string
- valued options, e.g. file=../fred, and numeric options - these may be in any base
- between 2 and 36 or autobase, which follows the C convention for constants. Multiple
- numeric value options are also parsed, e.g. tabs=4,7,23, and return as a vector the
- first element being the number of values found. As well as parsing options the library
- provides for displaying a table of options on request. Run the demo program - which is
- the only "proper" documentation (sorry, but I've never got around to it).
-
- Installation
- ============
-
- Run make. Copy cset.a & cset.h to suitable directories.
-
- History
- =======
-
- Many years ago I used a Honeywell GCOS/TSS system and the B language from the University of
- Waterloo, Ontario. The B language came with a command line parser library, bset(). I extended
- that library, adding options to print the argument table etc. and standardised all the commands
- on the TSS system (plus some other major hacking, but enough said...). Later I rewrote the whole
- library from scratch in C for Unix.
-
- Acknowlegements
- ===============
-
- To the people at Waterloo for the original idea.
- To by boss at the time - which is the reason for the detailed copyright notice
- [We had an offical agreement, anything I wrote and distributed could either be
- sold at a price set by him with me getting a percentage, or if I disagreed with
- his proposed price I could overrule and distribe it free...]
-
- If anybody writes some proper manual pages, please send me a copy!
-
- Nigel Perry
- Dept of Computing
- Imperial College
- London SW7
- England
-
- np@uk.ac.ic.doc
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'abbrev.c'
- then
- echo shar: will not over-write existing file "'abbrev.c'"
- else
- cat << \SHAR_EOF > 'abbrev.c'
- static char rcsid[] = "$Header";
- /* $Log: abbrev.c,v $
- * Revision 1.1 89/03/03 12:53:21 np
- * Initial revision
- *
- */
-
- /*
- * Copyright (C) 1985-1989 Nigel Perry
- *
- * This program is distributed without any warranty.
- * The author and and distributors accept no resposibility
- * to anyone for the consequence of using this program or
- * whether it serves any particular purpose or works at all,
- * unless they say so in writing.
- *
- * Everyone is granted permission to copy, modify and
- * redistribute this program, but only provided that:
- *
- * 1) They do so without financial or material gain.
- *
- * 2) The copyright notice and this notice are preserved on
- * all copies.
- *
- * 3) The original source is preserved in any redistribution.
- *
- * I hope you find this program useful!
- *
- */
-
- #define repeat while(1) /* try to make C look high level! */
-
- #define REQUIRED 32
- #define OPTIONAL 1
-
- /* check if string is a valid abbreviation of pattern
- *
- * In a pattern:
- * a thru z and _ are optional
- * other characters must be present
- *
- * Return:
- * -1 : no match
- * n = REQUIRED * (number of required matches) + OPTIONAL * (number of optional characters matched)
- *
- * e.g
- * Pattern String Return
- * LineFeed lf 2 * REQUIRED
- * Longform lf 1 * REQUIRED + 1 * OPTIONAL
- * => lf is a better match for LineFeed
- *
- * The higher the result the better the match.
- *
- */
-
- int abbrev(pat, str) register char *pat, *str;
- { register char c, pc;
- register int score, sc;
-
- score = 0;
- c = *str++;
- if(c >= 'a' && c <= 'z') c += 'A' - 'a';
- repeat
- if( (pc = *pat++) == '\0' ) /* this SHOULD be a case... */
- return( c == '\0' ? score : -1 );
- else if(pc == '_') /* optional */
- { if(c != '_') continue; /* try next pattern character */
- if( (sc = abbrev(pat, str)) >= 0 ) return(score + OPTIONAL + sc);
- /* rest of match failed, try next pattern char */
- }
- else if(pc >= 'a' && pc <= 'z') /* = case 'a' :: 'z', B rules! */
- { if( (c - 'A' + 'a') != pc ) continue; /* no match, try next pat */
- if( (sc = abbrev(pat, str)) >= 0 ) return(score + OPTIONAL + sc);
- }
- else /* must match */
- { if(c != pc) return(-1);
- score += REQUIRED;
- c = *str++; /* get next str char */
- if(c >= 'a' && c <= 'z') c += 'A' - 'a';
- }
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'cset.c'
- then
- echo shar: will not over-write existing file "'cset.c'"
- else
- cat << \SHAR_EOF > 'cset.c'
- static char rcsid[] = "$Header: cset.c,v 1.1 89/03/03 12:53:22 np Exp $";
- /* $Log: cset.c,v $
- * Revision 1.1 89/03/03 12:53:22 np
- * Initial revision
- *
- */
-
- /*
- * Copyright (C) 1985-1989 Nigel Perry
- *
- * This program is distributed without any warranty.
- * The author and and distributors accept no resposibility
- * to anyone for the consequence of using this program or
- * whether it serves any particular purpose or works at all,
- * unless they say so in writing.
- *
- * Everyone is granted permission to copy, modify and
- * redistribute this program, but only provided that:
- *
- * 1) They do so without financial or material gain.
- *
- * 2) The copyright notice and this notice are preserved on
- * all copies.
- *
- * 3) The original source is preserved in any redistribution.
- *
- * I hope you find this program useful!
- *
- */
-
- #include <stdio.h>
- #include "cset.h"
- #include "cset.d"
-
- #define strequ(a, b) (!strcmp(a,b))
-
- extern char *malloc(), *realloc();
-
- /* args:
- * args - array of char *'s to args (i.e. argv from main())
- * helpexit - exit program iff help given
- * return:
- * array of _opt_desc describing options
- */
-
- _opt_desc *_cset(args, helpexit) char **args;
- { char *name, *value, *info, *offset, *left, *right;
- int i, type, maxopt, max, score, helpgiven, len;
- _opt_entry *help_entry, *cp, *p;
- int do_help_entry;
- int super;
- _opt_desc *result, *resvec;
- extern _opt_entry _optable[];
- extern char *index();
-
- helpgiven = do_help_entry = 0;
- super = getuid() == 0; /* we be a super user */
-
- /* find largest option number, last entry in _optable is help_entry */
- help_entry = _optable;
- maxopt = 1;
- while( help_entry->_opt_pat ) { help_entry++; maxopt++; }
-
- /* get a vector for the result */
- for(i = 0; args[i]; i++); /* required length */
- resvec = result = (_opt_desc *) malloc( sizeof(_opt_desc) * (i + 1) );
- result[i]._opt_num = -1; /* flag end */
-
- for(i = 0; info = args[i]; i++)
- { if(*info == '+') /* +option */
- { name = info + 1;
- type = PLUS_KWD;
- result->_opt_type = '+';
- }
- else if(*info == '-') /* -option */
- { name = info + 1;
- type = DASH_KWD;
- result->_opt_type = '-';
- }
- else if(value = index(info, '='))
- { if(value != info) /* option=value */
- { name = info;
- *value++ = '\0'; /* add eos over =, bump ptr to value */
- if( *value == '\0' && args[i+1] != 0 ) /* option= value */
- value = args[++i];
- type = (SVAL_KWD | NVAL_KWD);
- result->_opt_type = '=';
- }
- else /* =<something> */
- { value++; /* ptr to <something> */
- if( strequ(value, "=") ) /* display complete option table */
- { d_optable(0, (_opt_entry *)0, super);
- helpgiven = 1;
- continue; /* don't wan't to scan optable, go direct to next */
- }
- else if( strequ(value, "+") ) /* display long optable */
- { d_optable(1, (_opt_entry *)0, super);
- helpgiven = 1;
- continue; /* don't wan't to scan optable, go direct to next */
- }
- else if( strequ(value, "#") ) /* display help info */
- { if(help_entry->_opt_types == 0)
- fprintf(stderr, "Sorry, no help available, see manual\n");
- else
- do_help_entry = 1;
- helpgiven = 1;
- continue; /* don't wan't to scan optable, go direct to next */
- }
- else /* see if <something> is an option */
- { /* scan optable for match */
- max = 0; /* best match so far */
- cp = (_opt_entry *)0;
- p = _optable;
- while( p->_opt_pat )
- { if( super || !(p->_opt_types & PRIV_BIT) )
- { if( (score = abbrev(p->_opt_pat, value)) > max )
- { max = score;
- cp = p;
- }
- }
- p++;
- }
- if(cp) /* got a match - print help message */
- { _opt_adorn(cp->_opt_types, &left, &right);
- len = strlen(left) + strlen(cp->_opt_pat) + strlen(right);
- fprintf(stderr, "%*s%s%s%s%*s%s\n", TAB1, "",
- left, cp->_opt_pat, right,
- TAB3 - (len + TAB1), "",
- cp->_opt_help == (char *)0 ? "(see manual)" : cp->_opt_help);
- helpgiven = 1;
- continue; /* don't wan't to scan optable */
- }
- else /* treat as possible BLNK_KWD */
- { name = info;
- type = BLNK_KWD | (i == 0 ? COMM_KWD : 0);
- result->_opt_type = ' ';
- }
- }
- }
- }
- else
- { name = info;
- type = BLNK_KWD | (i == 0 ? COMM_KWD : 0 );
- result->_opt_type = ' ';
- }
-
- /* scan optable for match */
- max = 0; /* best match so far */
- cp = (_opt_entry *)0;
- p = _optable;
- while( p->_opt_pat )
- { if( super || !(p->_opt_types & PRIV_BIT) ) /* check for PRIV_KWD */
- { if( p->_opt_types & type ) /* compatible type? */
- { if( (score = abbrev(p->_opt_pat, name)) > max )
- { /* better match */
- max = score;
- cp = p;
- }
- }
- }
- p++;
- }
- if(cp)
- { result->_opt_num = (int)(cp - _optable) + 1;
- switch( cp->_opt_types & type )
- { case SVAL_KWD:
- result->_opt.sval = value;
- break;
- case NVAL_KWD:
- if( read_num(value, cp->_opt_types, result) == 0 )
- { result->_opt_num = maxopt + 1; /* read_num failed */
- result->_opt.sval = info; /* return 'looks like' */
- }
- break;
- }
- }
- else if( type == BLNK_KWD )
- { result->_opt_num = 0; /* flag as a simple string */
- result->_opt.sval = info;
- }
- else
- { result->_opt_num = maxopt + 1; /* flag as looks like an option */
- result->_opt.sval = info;
- }
- result++; /* bump ptr */
- }
- result->_opt_num = -1; /* flag end */
-
- /* should we do help_entry */
- if( do_help_entry ) switch( help_entry->_opt_types )
- { case OPT_LIST:
- list_file(help_entry->_opt_help);
- break;
- case OPT_EXEC:
- system(help_entry->_opt_help);
- break;
- }
-
- /* see if we should exit... */
- if( helpexit && helpgiven ) exit(0);
- return(resvec);
- }
-
- #define CHUNK (sizeof(int) * 10)
-
- static read_num(str, type, result) char *str; _opt_desc *result;
- { int base, flag, offset, *mvals, maxnums, i;
-
- flag = 0; /* dont skip leading junk */
- offset = 0;
- base = type & BASE_MASK;
- if( !(type & MVAL_BIT) ) /* single number */
- { result->_opt.nval = numarg(str, &offset, base, &flag);
- if( flag == 0 || str[offset] != '\0' ) /* bad num or terminator */
- return(0); /* fail */
- }
- else /* multivalued */
- { maxnums = CHUNK;
- mvals = (int *)malloc(CHUNK);
- i = 1; /* mvals[0] will be number of numbers */
- do
- { if(i == maxnums) /* run out of space */
- { maxnums += CHUNK;
- mvals = (int *)realloc(mvals, CHUNK); /* grow it */
- }
- flag = 0;
- mvals[i++] = numarg(str, &offset, base, &flag);
- if(flag == 0) /* bad input */
- { free(mvals); /* give back vector */
- return(0);
- }
- } while( str[offset++] != '\0' );
- mvals[0] = i - 1; /* number of numbers found */
- result->_opt.mval = mvals;
- }
- return(1); /* ok */
- }
-
- static list_file(f) char *f;
- { FILE *in;
- char c;
-
- if( (in = fopen(f, "r")) == NULL ) return;
- while( (c = getc(in)) != EOF ) putc(c, stderr);
- fclose(in);
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'cset.d'
- then
- echo shar: will not over-write existing file "'cset.d'"
- else
- cat << \SHAR_EOF > 'cset.d'
- /* $Header: cset.d,v 1.1 89/03/03 12:53:22 np Exp $
- * $Log: cset.d,v $
- Revision 1.1 89/03/03 12:53:22 np
- Initial revision
-
- */
-
- /* defines for cset source files */
-
- /*
- * Copyright (C) 1985-1989 Nigel Perry
- *
- * This program is distributed without any warranty.
- * The author and and distributors accept no resposibility
- * to anyone for the consequence of using this program or
- * whether it serves any particular purpose or works at all,
- * unless they say so in writing.
- *
- * Everyone is granted permission to copy, modify and
- * redistribute this program, but only provided that:
- *
- * 1) They do so without financial or material gain.
- *
- * 2) The copyright notice and this notice are preserved on
- * all copies.
- *
- * 3) The original source is preserved in any redistribution.
- *
- * I hope you find this program useful!
- *
- */
-
- #define TAB1 5 /* offset for first option in table */
- #define TAB2 40 /* offset of 2nd option in table */
- #define TAB3 25 /* offset to help text */
-
- #define MVAL_BIT (MVAL_KWD ^ NVAL_KWD) /* =0x4000 */
- #define PRIV_BIT (PRIV_KWD ^ HIDE_KWD) /* =0x20000 */
- #define BASE_MASK 0xFF /* base of numeric keyword */
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'cset.h'
- then
- echo shar: will not over-write existing file "'cset.h'"
- else
- cat << \SHAR_EOF > 'cset.h'
- /* $Header: cset.h,v 1.1 89/03/03 12:53:23 np Exp $
- * $Log: cset.h,v $
- * Revision 1.1 89/03/03 12:53:23 np
- * Initial revision
- *
- */
-
- /*
- * Copyright (C) 1985-1989 Nigel Perry
- *
- * This program is distributed without any warranty.
- * The author and and distributors accept no resposibility
- * to anyone for the consequence of using this program or
- * whether it serves any particular purpose or works at all,
- * unless they say so in writing.
- *
- * Everyone is granted permission to copy, modify and
- * redistribute this program, but only provided that:
- *
- * 1) They do so without financial or material gain.
- *
- * 2) The copyright notice and this notice are preserved on
- * all copies.
- *
- * 3) The original source is preserved in any redistribution.
- *
- * I hope you find this program useful!
- *
- */
-
- /* a type definition for the options table */
- typedef struct { char *_opt_pat; int _opt_types; char *_opt_help } _opt_entry;
- #define OPTIONS _opt_entry _optable[] =
- /* the end of list marker for above defn */
- #define OPT_END { (char *)0, 0, (char *)0 }
- /* end of list marker including details of an info file */
- #define OPT_HELP(act, str) { (char *)0, act, str }
- /* empty help message constant */
- #define NOHELP (char *)0
- /* 'actions' for OPT_HELP, must be != 0 */
- #define OPT_LIST 1
- #define OPT_EXEC 2
-
- /* the option types */
- #define BLNK_KWD 0x00100 /* keyword */
- #define PLUS_KWD 0x00200 /* +keyword */
- #define DASH_KWD 0x00400 /* -keyword */
- #define COMM_KWD 0x00800 /* keyword - only recognised if command (first)*/
- #define SVAL_KWD 0x01000 /* keyword=string */
- #define NVAL_KWD 0x02000 /* keyword=number - 0ddd => oct, 0xddd => hex */
- #define MVAL_KWD 0x06000 /* keyword=number,...,number */
- #define DVAL_KWD 0x0200a /* keyword=decimal */
- #define MDVL_KWD 0x0600a /* keyword=decimal,...,decimal */
- #define OVAL_KWD 0x02008 /* keyword=octal */
- #define MOVL_KWD 0x06008 /* keyword=octal,...,octal */
- #define HVAL_KWD 0x02010 /* keyword=hex */
- #define MHVL_KWD 0x06010 /* keyword=hex,...,hex */
- #define HIDE_KWD 0x10000 /* Hidden keyword - not shown by d_optable() */
- #define PRIV_KWD 0x30000 /* Priviledged keyword - only for su's */
-
- /* _cset() returns a pointer to an array of... */
- typedef struct { int _opt_num;
- char _opt_type;
- union { int nval; /* numeric value */
- int *mval; /* ptr to vec of values */
- char *sval; /* string value */
- } _opt;
- } _opt_desc;
-
- extern _opt_desc *_cset();
-
- /* defn for environ var to control use of keyword arguments */
- #define AS_ENVAR "ArgStyle"
- #define AS_KWD "keyword" /* arg style is keyword */
- #define AS_ORG "original" /* arg style as supplied */
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'd_optable.c'
- then
- echo shar: will not over-write existing file "'d_optable.c'"
- else
- cat << \SHAR_EOF > 'd_optable.c'
- static char rcsid[] = "$Header: d_optable.c,v 1.1 89/03/03 12:53:23 np Exp $";
- /* $Log: d_optable.c,v $
- * Revision 1.1 89/03/03 12:53:23 np
- * Initial revision
- *
- */
-
- /*
- * Copyright (C) 1985-1989 Nigel Perry
- *
- * This program is distributed without any warranty.
- * The author and and distributors accept no resposibility
- * to anyone for the consequence of using this program or
- * whether it serves any particular purpose or works at all,
- * unless they say so in writing.
- *
- * Everyone is granted permission to copy, modify and
- * redistribute this program, but only provided that:
- *
- * 1) They do so without financial or material gain.
- *
- * 2) The copyright notice and this notice are preserved on
- * all copies.
- *
- * 3) The original source is preserved in any redistribution.
- *
- * I hope you find this program useful!
- *
- */
-
- #include <stdio.h>
- #include "cset.h"
- #include "cset.d"
-
- #define next continue
-
- /* Pretty print an _optable - or try to, boring ol' stdio!
-
- Adapted from d.optab - written in the REAL language B Plus!
-
- args:
- withelp - true is want long form with short desc
- table - the table to be printed, 0 => _optable
- hidden - if true, the 'hidden' options are also printed
- */
-
- d_optable(withelp, table, hidden) int withelp, hidden; _opt_entry *table;
- { extern _opt_entry _optable[];
- _opt_entry *p;
- int c, n, flip, column;
- char *left, *right;
-
- /* set default table */
- if( table == (_opt_entry *)0 ) table = _optable;
-
- p = table;
- flip = c = n = 0;
- /* count command and option names */
- while(p->_opt_pat) if((p++)->_opt_types == COMM_KWD) c++; else n++;
- if(c > 1) /* only list command names if > 1 */
- { fputs("Command Names:", stderr);
- p = table;
- while(p->_opt_pat)
- { if(p->_opt_types == COMM_KWD)
- { if(withelp)
- { fprintf(stderr, "\n%*s%s%*s%s", TAB1, "", p->_opt_pat,
- TAB3 - (strlen(p->_opt_pat) + TAB1), "",
- p->_opt_help == NOHELP ? "(see manual)" : p->_opt_help);
- }
- else
- { fprintf(stderr, "%sc%*s%s", flip ? (char *)0 : "\n",
- flip ? (TAB2 - column) : TAB1, "", p->_opt_pat);
- if(flip = !flip) column = TAB1 + strlen(p->_opt_pat);
- }
- }
- p++;
- }
- fputc('\n', stderr);
- if(!n) return;
- }
- fputs("Options:", stderr);
- flip = 0;
- p = table; p--;
- while( (++p)->_opt_pat )
- { if(p->_opt_types == COMM_KWD) next;
- /* if HIDE and not hidden don't print it! */
- if( (p->_opt_types & HIDE_KWD) && !hidden) next;
- _opt_adorn(p->_opt_types, &left, &right);
- if(withelp)
- { fprintf( stderr, "\n%*s%s%s%s%*s%s", TAB1, "", left, p->_opt_pat,
- right,
- TAB3 - (TAB1+strlen(left)+strlen(p->_opt_pat)+strlen(right)),
- "", p->_opt_help == NOHELP ? "(see manual)" : p->_opt_help);
- }
- else
- { fprintf( stderr, "%s%*s", flip ? "" : "\n",
- flip ? (TAB2 - column) : TAB1, "");
- flip = !flip;
- fprintf(stderr, "%s%s%s", left, p->_opt_pat, right);
- if(flip)
- column = TAB1 + strlen(left) + strlen(p->_opt_pat) + strlen(right);
- }
- }
- fputc('\n', stderr);
- }
-
- /* return strings to 'adorn' options */
- _opt_adorn(p, left, right) char **left, **right;
- { static char *dpb[] = { (char *)0, "", "+", "[+]", "-", "[-]",
- "(+|-)", "[+|-]" };
- static char *s_val = { "=X" };
- static char *m_val = { "=X,...,X" };
- int c;
- if(p == COMM_KWD)
- *left = *right = "";
- else if(c = p & (DASH_KWD | PLUS_KWD | BLNK_KWD))
- { *left = dpb[c >> 8];
- *right = "";
- }
- else if(p == SVAL_KWD)
- { *left = "";
- s_val[1] = 's'; /* construct '=s' */
- *right = s_val;
- }
- else /* numeric */
- { switch(p & 0xFF) /* find base */
- { case 0: c = 'n'; break;
- case 8: c = 'o'; break;
- case 10: c = 'd'; break;
- case 16: c = 'x'; break;
- default: /* somebody is being ackward... */
- c = p & 0xFF;
- c += c < 10 ? '0' : ('A' - 10);
- }
- *left = "";
- if(p & MVAL_BIT)
- { m_val[1] = m_val[7] = c;
- *right = m_val;
- }
- else
- { s_val[1] = c;
- *right = s_val;
- }
- }
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'demo.c'
- then
- echo shar: will not over-write existing file "'demo.c'"
- else
- cat << \SHAR_EOF > 'demo.c'
- /* demonstration of _cset */
-
- #include "cset.h"
-
- OPTIONS
- { "DEMO", COMM_KWD, "a command name",
- "Tesco", COMM_KWD, "another command name",
- "String", SVAL_KWD, "an arbitrary string",
- "Number", NVAL_KWD, "a number, base 8, 10 or 16",
- "Tabs", MVAL_KWD, "list of tab stops",
- "Wide", PLUS_KWD, "turn an option on",
- "Multi", PLUS_KWD | DASH_KWD | BLNK_KWD, "option may be +, - or plain string",
- "Hidden", HIDE_KWD | NVAL_KWD | 19, "hidden numeric base 19 argument!",
- OPT_HELP(OPT_EXEC, "more README")
- };
-
- #define STRING 0
- #define DEMO 1
- #define TESCO (DEMO+1)
- #define STR (TESCO+1)
- #define NUM (STR+1)
- #define TABS (NUM+1)
- #define WIDE (TABS+1)
- #define MULTI (WIDE+1)
- #define HID (MULTI+1)
-
- /* I'm sure I should be able to do this in one go..., but the compiler barfs */
- char *d1[] = {"demo", "st=asda", (char *)0};
- char *d2[] = {"demo", "tesco", "num=0xd", "l=57", "+g", (char *)0};
- char *d3[] = {"tesco", "+w", "-mu", "+mt", "muti", (char *)0};
- char *d4[] = {"demo", "h=beef t=09,9,0x9", (char *)0};
- char *d5[] = {"demo", "==", (char *)0};
- char *d6[] = {"demo", "=hi", "=+", "=#", (char *)0};
-
- char **Demos[] =
- { d1, d2, d3, d4, d5, d6,
- (char **)0
- };
-
- execute(cmd, args)
- char *cmd, **args;
- { if( fork() )
- wait(0);
- else
- execv(cmd, args);
- };
-
- main(argc, argv) char **argv;
- { _opt_desc *parsed;
- char ***dp, **cmd;
- int *p, num;
-
- if(argc <= 1)
- { /* no arguments, do demos */
- dp = Demos;
- while(*dp != (char **)0)
- { printf("\n************************\nExecuting:");
- cmd = *dp;
- while(*cmd != (char *)0) printf(" %s", *cmd++);
- printf("\nGives:\n\n");
- execute("./demo", *dp++);
- }
- return;
- }
-
- parsed = _cset(argv, 1);
-
- while( parsed->_opt_num != -1 )
- { switch( parsed->_opt_num )
- { case STRING:
- printf("Arbitrary string option: %s\n", parsed->_opt.sval); break;
- case DEMO:
- break;
- case TESCO:
- printf("Called using alternative command name \"tesco\"\n"); break;
- case NUM:
- printf("Numeric value: 0%o, %d, 0x%x\n", parsed->_opt.nval, parsed->_opt.nval, parsed->_opt.nval); break;
- case STR:
- printf("String valued option: %s\n", parsed->_opt.sval); break;
- case HID:
- printf("Hidden keyword, number input in base 19 = %d in decimal\n", parsed->_opt.nval);
- case MULTI:
- printf("Option may be +, - or blank, this time it was: '%c'\n", parsed->_opt_type);
- break;
- case WIDE:
- printf("Wide option turned on\n"); break;
- case TABS:
- p = parsed->_opt.mval;
- printf("Muliple numeric valued keyword with %d values:", (num = *p++));
- while(num--) printf(" %d", *p++);
- printf("\n");
- break;
- default: /* out of range - looks like an option but didn't match */
- printf("Unknown option: %s\n", parsed->_opt.sval );
-
- }
- parsed++;
- }
- }
-
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'makefile'
- then
- echo shar: will not over-write existing file "'makefile'"
- else
- cat << \SHAR_EOF > 'makefile'
- # $Header: makefile,v 1.1 89/03/03 12:53:24 np Exp $
- all: cset.a demo
-
- demo: demo.c cset.a
- cc -o demo demo.c cset.a
- cset.a: cset.o d_optable.o numarg.o abbrev.o not_kwd.o
- ranlib cset.a
- cset.o: cset.c cset.d
- cc -c cset.c
- ar rv cset.a cset.o
- .c.o:; cc -c $*.c
- ar rv cset.a $*.o
-
- cleanup:
- rm *.o
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'not_kwd.c'
- then
- echo shar: will not over-write existing file "'not_kwd.c'"
- else
- cat << \SHAR_EOF > 'not_kwd.c'
- static char rcsid[] = "$Header: not_kwd.c,v 1.1 89/03/03 12:53:25 np Exp $";
- /* $Log: not_kwd.c,v $
- * Revision 1.1 89/03/03 12:53:25 np
- * Initial revision
- *
- */
-
- /*
- * Copyright (C) 1985-1989 Nigel Perry
- *
- * This program is distributed without any warranty.
- * The author and and distributors accept no resposibility
- * to anyone for the consequence of using this program or
- * whether it serves any particular purpose or works at all,
- * unless they say so in writing.
- *
- * Everyone is granted permission to copy, modify and
- * redistribute this program, but only provided that:
- *
- * 1) They do so without financial or material gain.
- *
- * 2) The copyright notice and this notice are preserved on
- * all copies.
- *
- * 3) The original source is preserved in any redistribution.
- *
- * I hope you find this program useful!
- *
- */
-
- /* do execv if AS_ENVAR not set to AS_KWD
- * enables programs to switch the option format according to the environment setting
- */
-
- #include "cset.h"
-
- not_kwd(object, args) register char *object, **args;
- { register char *val;
- extern char *getenv();
-
- if( (val = getenv(AS_ENVAR)) == (char *)0 || strcmp(val, AS_KWD) != 0 )
- execv(object, args);
- }
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'numarg.c'
- then
- echo shar: will not over-write existing file "'numarg.c'"
- else
- cat << \SHAR_EOF > 'numarg.c'
- static char rcsid[] = "$Header: numarg.c,v 1.1 89/03/03 12:53:25 np Exp $";
- /* $Log: numarg.c,v $
- * Revision 1.1 89/03/03 12:53:25 np
- * Initial revision
- *
- */
-
- /*
- * Copyright (C) 1985-1989 Nigel Perry
- *
- * This program is distributed without any warranty.
- * The author and and distributors accept no resposibility
- * to anyone for the consequence of using this program or
- * whether it serves any particular purpose or works at all,
- * unless they say so in writing.
- *
- * Everyone is granted permission to copy, modify and
- * redistribute this program, but only provided that:
- *
- * 1) They do so without financial or material gain.
- *
- * 2) The copyright notice and this notice are preserved on
- * all copies.
- *
- * 3) The original source is preserved in any redistribution.
- *
- * I hope you find this program useful!
- *
- */
-
- #define repeat while(1)
-
- /* convert string to number
- * args:
- * str: ptr to string to be parsed
- * poffset: ptr to offset into str at which to start, will be updated on exit
- * base: base of number to parse (2 -> 36), < 2 implies 0ddd -> oct, 0xddd -> hex, ddd -> dec
- * pflag: ptr to flag, on input *pflag = 1 => skip leading junk (blanks always skipped)
- * on exit *pflag = 0 => failed to parse number
- * return:
- * *pflag = 1 => number parsed
- * *pflag = 0 => 0, failed to parse
- *
- */
-
- int numarg(str, poffset, base, pflag) register char *str;
- register int base, *poffset, *pflag;
- { int neg, autobase;
- register int val, dig;
- char *start;
- register char c;
-
- neg = autobase = val = 0;
-
- /* if base < 2, set oct/dec/hex */
- if(base < 2) { base = 10; autobase = 1; }
-
- start = str; /* save start */
- str += *poffset; /* add in starting offset */
-
- /* find first digit */
- repeat
- { switch(c = *str++)
- { case ' ': continue; /* skip leading blanks */
- case '-': neg = 1; /* flag negative */
- case '+': if( (dig = getdig(*str++, base)) < 0 )
- { *poffset = str - start;
- return(*pflag = 0); /* error */
- }
- break;
- default: if( (dig = getdig(c, base)) >= 0 )
- break; /* good digit */
- if( *pflag == 1 ) continue; /* skip leading junk */
- *poffset = str - start;
- return(*pflag = 0); /* junk in de way */
- }
- break; /* kill repeat */
- }
-
- /* if get here, dig is first digit & neg flag be set */
- if(dig == 0 && autobase) /* check for oct/hex */
- { if( (c = *str) == 'x' || c == 'X' ) /* hex */
- { str++; /* skip x */
- base = 16;
- }
- else
- base = 8;
- }
- else
- val = dig;
-
- /* read in till non-digit */
- while( (dig = getdig(*str++, base)) >= 0 ) val = val * base + dig;
-
- *poffset = str - start - 1;
- *pflag = 1; /* good return */
- return(neg ? -val : val);
- }
-
- static getdig(c, base) register int c, base;
- { if( c >= '0' && c <= '9' ) /* this SHOULD be a case... B rules! */
- return( (c -= '0') < base ? c : -1 );
- else if( c >= 'a' && c <= 'z' )
- return( (c += 10 - 'a') < base ? c : -1 );
- else if(c >= 'A' && c <= 'Z' )
- return( (c += 10 - 'A') < base ? c : -1);
- else return(-1);
- }
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
- ---
- Nigel Perry Department of Computing
- Imperial College
- Janet: np@uk.ac.ic.doc London
- DARPA: np%uk.ac.ic.doc@ucl-cs SW7
- Uucp: np@icdoc.UUCP, ukc!icdoc!np England
-